package cn.lyjuan.payment.third.base.pay.chl.impl.weixin.util;

import cn.lyjuan.base.util.DigestUtils;
import cn.lyjuan.base.util.HttpUtils;
import cn.lyjuan.base.util.XmlUtils;
import cn.lyjuan.payment.third.base.pay.chl.impl.weixin.bean.WxChlCnf;
import cn.lyjuan.payment.third.base.pay.cst.PayConst;
import cn.lyjuan.payment.third.base.pay.enums.SimpleStatusEnum;
import cn.lyjuan.payment.third.base.pay.vo.res.RefundRes;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

/**
 * 微信退款
 */
@Slf4j
public class WxpayRefund {

    public static final String REFUND_URL = "https://api.mch.weixin.qq.com/secapi/pay/refund";

    /**
     * 创建微信手机网页支付授权
     *
     * @param cnf
     * @return
     */
    public static String createTradeAuth(String selfRefundOrderNo, String localNo, Integer totalAmt, Integer amt, WxChlCnf cnf) {
        Map<String, String> params = createTradeRefundParam(selfRefundOrderNo, localNo, totalAmt, amt, cnf);
        // 32位 MD5 签名字符串
        String signStr = WxUtils.sortParamForSign(params);
        // 根据密钥进行 MD5 签名
        String sign = DigestUtils.md5LowerCase(signStr + "&key=" + cnf.getKey(),
                PayConst.CHARSET);
        params.put("sign", sign.toUpperCase());
        // 拼接参数为XML
        String xml = WxUtils.sortParamXml(params);
        return xml;
    }

    private static Map<String, String> createTradeRefundParam(String selfRefundOrderNo, String localNo, Integer totalAmt, Integer amt, WxChlCnf cnf) {
        Map<String, String> params = new HashMap<>(7);
        // 公众号
        params.put("appid", cnf.getAppId());
        // 商户号
        params.put("mch_id", cnf.getMchId());
        params.put("nonce_str", UUID.randomUUID().toString().replaceAll("-", ""));
        // 商户订单号
        params.put("out_trade_no", localNo);
        // 本平台退款订单号
        params.put("out_refund_no", selfRefundOrderNo);
        // 金额，分为单位
        params.put("total_fee", Integer.toString(totalAmt));
        // 金额，分为单位
        params.put("refund_fee", Integer.toString(amt));
        return params;
    }

    /**
     * 微信交易授权
     *
     * @param tradeAuthXml
     * @return
     */
    public static Map<String, String> sendTradeAuth(String tradeAuthXml) {
        // 提交支付预请求
        String result = null;
        try {
            result = HttpUtils.sendPost(REFUND_URL, tradeAuthXml, false, PayConst.CHARSET, null);
            System.out.println("请求参数++++++++++++++++++++++++》" + tradeAuthXml);
            System.out.println("返回参数++++++++++++++++++++++++》" + result);
        } catch (Exception e) {
            log.error("wx send trade auth error", e);
            Map<String, String> params = new HashMap<>(2);
            params.put("return_code", "FAIL");
            params.put("return_msg", e.getMessage());
            return params;
        }
        // 解析结果
        return parseAuthTradeRes(result);
    }

    /**
     * 创建微信手机网页支付交易信息
     *
     * @param cnf  支付渠道配置信息
     * @param auth 订单号
     * @return
     */
    public static RefundRes convertResponseToRefundRes(String localNo, WxChlCnf cnf, Map<String, String> auth) {
        // 判断是否成功
        if (!WxpaySubmit.SUCC.equalsIgnoreCase(auth.get("return_code"))
                || !WxpaySubmit.SUCC.equalsIgnoreCase(auth.get("result_code"))) {
            return new RefundRes(SimpleStatusEnum.FAIL, auth.get("err_code") + ":" + auth.get("return_msg") + ":" + auth.get("err_code_des"));
        }
        return new RefundRes(SimpleStatusEnum.SUCC, "SUCC", auth.get("transaction_id"));
    }

    /**
     * 解析微信手机网页授权结果
     *
     * @param result
     * @return
     */
    public static Map<String, String> parseAuthTradeRes(String result) {
        Map<String, String> params = new HashMap<String, String>();

        params.put("return_code", XmlUtils.getMember(result, "return_code"));
        params.put("return_msg", XmlUtils.getMember(result, "return_msg"));
        params.put("appid", XmlUtils.getMember(result, "appid"));
        params.put("mch_id", XmlUtils.getMember(result, "mch_id"));
        params.put("device_info", XmlUtils.getMember(result, "device_info"));
        params.put("nonce_str", XmlUtils.getMember(result, "nonce_str"));
        params.put("sign", XmlUtils.getMember(result, "sign"));
        params.put("result_code", XmlUtils.getMember(result, "result_code"));
        params.put("err_code", XmlUtils.getMember(result, "err_code"));
        params.put("err_code_des", XmlUtils.getMember(result, "err_code_des"));
        params.put("trade_type", XmlUtils.getMember(result, "trade_type"));
        params.put("prepay_id", XmlUtils.getMember(result, "prepay_id"));
        params.put("code_url", XmlUtils.getMember(result, "code_url"));
        params.put("out_refund_no", XmlUtils.getMember(result, "out_refund_no"));
        params.put("transaction_id", XmlUtils.getMember(result, "transaction_id"));
        return params;
    }

}
